{
 "nbformat": 4,
 "nbformat_minor": 0,
 "metadata": {
  "colab": {
   "name": "Colab-UnityEnvironment-3-SideChannel.ipynb",
   "private_outputs": true,
   "provenance": [],
   "collapsed_sections": [],
   "toc_visible": true
  },
  "kernelspec": {
   "name": "python3",
   "language": "python",
   "display_name": "Python 3"
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pbVXrmEsLXDt"
   },
   "source": [
    "# ML-Agents Use SideChannels\n",
    "<img src=\"https://raw.githubusercontent.com/Unity-Technologies/ml-agents/release/4.0.0/docs/images/3dball_big.png\" align=\"middle\" width=\"435\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WNKTwHU3d2-l"
   },
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "htb-p1hSNX7D",
    "ExecuteTime": {
     "start_time": "2023-10-04T14:07:19.585847Z",
     "end_time": "2023-10-04T14:07:19.586641Z"
    }
   },
   "source": [
    "#@title Install Rendering Dependencies { display-mode: \"form\" }\n",
    "#@markdown (You only need to run this code when using Colab's hosted runtime)\n",
    "\n",
    "import os\n",
    "from IPython.display import HTML, display\n",
    "\n",
    "def progress(value, max=100):\n",
    "    return HTML(\"\"\"\n",
    "        <progress\n",
    "            value='{value}'\n",
    "            max='{max}',\n",
    "            style='width: 100%'\n",
    "        >\n",
    "            {value}\n",
    "        </progress>\n",
    "    \"\"\".format(value=value, max=max))\n",
    "\n",
    "pro_bar = display(progress(0, 100), display_id=True)\n",
    "\n",
    "try:\n",
    "  import google.colab\n",
    "  INSTALL_XVFB = True\n",
    "except ImportError:\n",
    "  INSTALL_XVFB = 'COLAB_ALWAYS_INSTALL_XVFB' in os.environ\n",
    "\n",
    "if INSTALL_XVFB:\n",
    "  with open('frame-buffer', 'w') as writefile:\n",
    "    writefile.write(\"\"\"#taken from https://gist.github.com/jterrace/2911875\n",
    "XVFB=/usr/bin/Xvfb\n",
    "XVFBARGS=\":1 -screen 0 1024x768x24 -ac +extension GLX +render -noreset\"\n",
    "PIDFILE=./frame-buffer.pid\n",
    "case \"$1\" in\n",
    "  start)\n",
    "    echo -n \"Starting virtual X frame buffer: Xvfb\"\n",
    "    /sbin/start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile --background --exec $XVFB -- $XVFBARGS\n",
    "    echo \".\"\n",
    "    ;;\n",
    "  stop)\n",
    "    echo -n \"Stopping virtual X frame buffer: Xvfb\"\n",
    "    /sbin/start-stop-daemon --stop --quiet --pidfile $PIDFILE\n",
    "    rm $PIDFILE\n",
    "    echo \".\"\n",
    "    ;;\n",
    "  restart)\n",
    "    $0 stop\n",
    "    $0 start\n",
    "    ;;\n",
    "  *)\n",
    "        echo \"Usage: /etc/init.d/xvfb {start|stop|restart}\"\n",
    "        exit 1\n",
    "esac\n",
    "exit 0\n",
    "    \"\"\")\n",
    "  !sudo apt-get update\n",
    "  pro_bar.update(progress(10, 100))\n",
    "  !sudo DEBIAN_FRONTEND=noninteractive apt install -y daemon wget gdebi-core build-essential libfontenc1 libfreetype6 xorg-dev xorg\n",
    "  pro_bar.update(progress(20, 100))\n",
    "  !wget http://security.ubuntu.com/ubuntu/pool/main/libx/libxfont/libxfont1_1.5.1-1ubuntu0.16.04.4_amd64.deb 2>&1\n",
    "  pro_bar.update(progress(30, 100))\n",
    "  !wget --output-document xvfb.deb http://security.ubuntu.com/ubuntu/pool/universe/x/xorg-server/xvfb_1.18.4-0ubuntu0.12_amd64.deb 2>&1\n",
    "  pro_bar.update(progress(40, 100))\n",
    "  !sudo dpkg -i libxfont1_1.5.1-1ubuntu0.16.04.4_amd64.deb 2>&1\n",
    "  pro_bar.update(progress(50, 100))\n",
    "  !sudo dpkg -i xvfb.deb 2>&1\n",
    "  pro_bar.update(progress(70, 100))\n",
    "  !rm libxfont1_1.5.1-1ubuntu0.16.04.4_amd64.deb\n",
    "  pro_bar.update(progress(80, 100))\n",
    "  !rm xvfb.deb\n",
    "  pro_bar.update(progress(90, 100))\n",
    "  !bash frame-buffer start\n",
    "  os.environ[\"DISPLAY\"] = \":1\"\n",
    "pro_bar.update(progress(100, 100))"
   ],
   "execution_count": 1,
   "outputs": [
    {
     "data": {
      "text/plain": "<IPython.core.display.HTML object>",
      "text/html": "\n        <progress\n            value='0'\n            max='100',\n            style='width: 100%'\n        >\n            0\n        </progress>\n    "
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Pzj7wgapAcDs"
   },
   "source": [
    "### Installing ml-agents"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "N8yfQqkbebQ5",
    "ExecuteTime": {
     "start_time": "2023-10-04T14:07:19.586390Z",
     "end_time": "2023-10-04T14:07:19.587185Z"
    }
   },
   "source": [
    "try:\n",
    "  import mlagents\n",
    "  print(\"ml-agents already installed\")\n",
    "except ImportError:\n",
    "  !python -m pip install -q mlagents==1.1.0\n",
    "  print(\"Installed ml-agents\")"
   ],
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ml-agents already installed\n"
     ]
    }
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "_u74YhSmW6gD"
   },
   "source": [
    "## Side Channel\n",
    "\n",
    "SideChannels are objects that can be passed to the constructor of a UnityEnvironment or the `make()` method of a registry entry to send non Reinforcement Learning related data.\n",
    "More information available [here](https://docs.unity3d.com/Packages/com.unity.ml-agents@latest/index.html?subfolder=/manual/Python-LLAPI.html#communicating-additional-information-with-the-environment)\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "U4RXnhLRk7Uc"
   },
   "source": [
    "### Engine Configuration SideChannel\n",
    "The [Engine Configuration Side Channel](https://docs.unity3d.com/Packages/com.unity.ml-agents@latest/index.html?subfolder=/manual/Python-LLAPI.html#engineconfigurationchannel) is used to configure how the Unity Engine should run.\n",
    "We will use the GridWorld environment to demonstrate how to use the EngineConfigurationChannel."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "YSf-WhxbqtLw",
    "ExecuteTime": {
     "start_time": "2023-10-04T14:07:19.586596Z",
     "end_time": "2023-10-04T14:07:21.264486Z"
    }
   },
   "source": [
    "# -----------------\n",
    "# This code is used to close an env that might not have been closed before\n",
    "try:\n",
    "  env.close()\n",
    "except:\n",
    "  pass\n",
    "# -----------------\n",
    "\n",
    "from mlagents_envs.registry import default_registry\n",
    "env_id = \"GridWorld\"\n",
    "\n",
    "# Import the EngineConfigurationChannel class\n",
    "from mlagents_envs.side_channel.engine_configuration_channel import EngineConfigurationChannel\n",
    "\n",
    "# Create the side channel\n",
    "engine_config_channel = EngineConfigurationChannel()\n",
    "\n",
    "# Pass the side channel to the make method\n",
    "# Note, the make method takes a LIST of SideChannel as input\n",
    "env = default_registry[env_id].make(side_channels = [engine_config_channel])\n",
    "\n",
    "# Configure the Unity Engine\n",
    "engine_config_channel.set_configuration_parameters(target_frame_rate = 30)\n",
    "\n",
    "env.reset()\n",
    "\n",
    "# ...\n",
    "# Perform experiment on environment\n",
    "# ...\n",
    "\n",
    "env.close()"
   ],
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[UnityMemory] Configuration Parameters - Can be set up in boot.config\n",
      "    \"memorysetup-bucket-allocator-granularity=16\"\n",
      "    \"memorysetup-bucket-allocator-bucket-count=8\"\n",
      "    \"memorysetup-bucket-allocator-block-size=4194304\"\n",
      "    \"memorysetup-bucket-allocator-block-count=1\"\n",
      "    \"memorysetup-main-allocator-block-size=16777216\"\n",
      "    \"memorysetup-thread-allocator-block-size=16777216\"\n",
      "    \"memorysetup-gfx-main-allocator-block-size=16777216\"\n",
      "    \"memorysetup-gfx-thread-allocator-block-size=16777216\"\n",
      "    \"memorysetup-cache-allocator-block-size=4194304\"\n",
      "    \"memorysetup-typetree-allocator-block-size=2097152\"\n",
      "    \"memorysetup-profiler-bucket-allocator-granularity=16\"\n",
      "    \"memorysetup-profiler-bucket-allocator-bucket-count=8\"\n",
      "    \"memorysetup-profiler-bucket-allocator-block-size=4194304\"\n",
      "    \"memorysetup-profiler-bucket-allocator-block-count=1\"\n",
      "    \"memorysetup-profiler-allocator-block-size=16777216\"\n",
      "    \"memorysetup-profiler-editor-allocator-block-size=1048576\"\n",
      "    \"memorysetup-temp-allocator-size-main=4194304\"\n",
      "    \"memorysetup-job-temp-allocator-block-size=2097152\"\n",
      "    \"memorysetup-job-temp-allocator-block-size-background=1048576\"\n",
      "    \"memorysetup-job-temp-allocator-reduction-small-platforms=262144\"\n",
      "    \"memorysetup-allocator-temp-initial-block-size-main=262144\"\n",
      "    \"memorysetup-allocator-temp-initial-block-size-worker=262144\"\n",
      "    \"memorysetup-temp-allocator-size-background-worker=32768\"\n",
      "    \"memorysetup-temp-allocator-size-job-worker=262144\"\n",
      "    \"memorysetup-temp-allocator-size-preload-manager=262144\"\n",
      "    \"memorysetup-temp-allocator-size-nav-mesh-worker=65536\"\n",
      "    \"memorysetup-temp-allocator-size-audio-worker=65536\"\n",
      "    \"memorysetup-temp-allocator-size-cloud-worker=32768\"\n",
      "    \"memorysetup-temp-allocator-size-gfx=262144\"\n"
     ]
    }
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "h1lIx3_l24OP"
   },
   "source": [
    "### Environment Parameters Channel\n",
    "The [Environment Parameters Side Channel](https://docs.unity3d.com/Packages/com.unity.ml-agents@latest/index.html?subfolder=/manual/Python-LLAPI.html#environmentparameters) is used to modify environment parameters during the simulation.\n",
    "We will use the GridWorld environment to demonstrate how to use the EngineConfigurationChannel."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "id": "dhtl0mpeqxYi",
    "ExecuteTime": {
     "start_time": "2023-10-04T14:09:13.046780Z",
     "end_time": "2023-10-04T14:09:14.768804Z"
    }
   },
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "\n",
    "# -----------------\n",
    "# This code is used to close an env that might not have been closed before\n",
    "try:\n",
    "  env.close()\n",
    "except:\n",
    "  pass\n",
    "# -----------------\n",
    "\n",
    "from mlagents_envs.registry import default_registry\n",
    "env_id = \"GridWorld\"\n",
    "\n",
    "# Import the EngineConfigurationChannel class\n",
    "from mlagents_envs.side_channel.environment_parameters_channel import EnvironmentParametersChannel\n",
    "\n",
    "# Create the side channel\n",
    "env_parameters = EnvironmentParametersChannel()\n",
    "\n",
    "# Pass the side channel to the make method\n",
    "# Note, the make method takes a LIST of SideChannel as input\n",
    "env = default_registry[env_id].make(side_channels = [env_parameters])\n",
    "\n",
    "env.reset()\n",
    "behavior_name = list(env.behavior_specs)[0]\n",
    "\n",
    "print(\"Observation without changing the environment parameters\")\n",
    "decision_steps, terminal_steps = env.get_steps(behavior_name)\n",
    "plt.imshow(np.moveaxis(decision_steps.obs[0][0,:,:,:], 0, -1))\n",
    "plt.show()\n",
    "\n",
    "print(\"Increasing the dimensions of the grid from 5 to 7\")\n",
    "env_parameters.set_float_parameter(\"gridSize\", 7)\n",
    "print(\"Increasing the number of X from 1 to 5\")\n",
    "env_parameters.set_float_parameter(\"numObstacles\", 5)\n",
    "\n",
    "# Any change to a SideChannel will only be effective after a step or reset\n",
    "# In the GridWorld Environment, the grid's dimensions can only change at reset\n",
    "env.reset()\n",
    "\n",
    "\n",
    "decision_steps, terminal_steps = env.get_steps(behavior_name)\n",
    "plt.imshow(np.moveaxis(decision_steps.obs[0][0,:,:,:], 0, -1))\n",
    "plt.show()\n",
    "\n",
    "\n",
    "\n",
    "env.close()"
   ],
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[UnityMemory] Configuration Parameters - Can be set up in boot.config\n",
      "    \"memorysetup-bucket-allocator-granularity=16\"\n",
      "    \"memorysetup-bucket-allocator-bucket-count=8\"\n",
      "    \"memorysetup-bucket-allocator-block-size=4194304\"\n",
      "    \"memorysetup-bucket-allocator-block-count=1\"\n",
      "    \"memorysetup-main-allocator-block-size=16777216\"\n",
      "    \"memorysetup-thread-allocator-block-size=16777216\"\n",
      "    \"memorysetup-gfx-main-allocator-block-size=16777216\"\n",
      "    \"memorysetup-gfx-thread-allocator-block-size=16777216\"\n",
      "    \"memorysetup-cache-allocator-block-size=4194304\"\n",
      "    \"memorysetup-typetree-allocator-block-size=2097152\"\n",
      "    \"memorysetup-profiler-bucket-allocator-granularity=16\"\n",
      "    \"memorysetup-profiler-bucket-allocator-bucket-count=8\"\n",
      "    \"memorysetup-profiler-bucket-allocator-block-size=4194304\"\n",
      "    \"memorysetup-profiler-bucket-allocator-block-count=1\"\n",
      "    \"memorysetup-profiler-allocator-block-size=16777216\"\n",
      "    \"memorysetup-profiler-editor-allocator-block-size=1048576\"\n",
      "    \"memorysetup-temp-allocator-size-main=4194304\"\n",
      "    \"memorysetup-job-temp-allocator-block-size=2097152\"\n",
      "    \"memorysetup-job-temp-allocator-block-size-background=1048576\"\n",
      "    \"memorysetup-job-temp-allocator-reduction-small-platforms=262144\"\n",
      "    \"memorysetup-allocator-temp-initial-block-size-main=262144\"\n",
      "    \"memorysetup-allocator-temp-initial-block-size-worker=262144\"\n",
      "    \"memorysetup-temp-allocator-size-background-worker=32768\"\n",
      "    \"memorysetup-temp-allocator-size-job-worker=262144\"\n",
      "    \"memorysetup-temp-allocator-size-preload-manager=262144\"\n",
      "    \"memorysetup-temp-allocator-size-nav-mesh-worker=65536\"\n",
      "    \"memorysetup-temp-allocator-size-audio-worker=65536\"\n",
      "    \"memorysetup-temp-allocator-size-cloud-worker=32768\"\n",
      "    \"memorysetup-temp-allocator-size-gfx=262144\"\n",
      "Observation without changing the environment parameters\n"
     ]
    },
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhQAAAGfCAYAAAAH5UtjAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAk3ElEQVR4nO3df3BU1f3/8dduyG6iwEZQNkQSjD+DP6AYNKxgWzEtQx0rhVq12OKP6mgD8sNWiQpoq8bqVPFHxGox1FGaEUdQbIXaKOFrGxAiqGgbUalEYYPWZgMomww53z/8uOPCXuXmbNzN5vmYuTPm3LMn75OLm1fu3nOvxxhjBAAAYMGb6gIAAEDPR6AAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADW+nTXwNXV1brrrrsUDoc1YsQI3X///Tr99NO/9nWdnZ3avn27+vXrJ4/H013lAQCAr2GM0a5du1RQUCCv92vOQZhuUFtba3w+n3n00UfNm2++aa644gqTl5dnWlpavva1zc3NRhIbGxsbGxtbmmzNzc1f+/vbY0zyHw5WVlam0047TQ888ICkz886FBYWavr06ZozZ85XvjYSiSgvL08Xnz9Rvuzs/fYmvVQAABAT/8lAe0eHHl+6XK2trQoEAl/5yqR/5NHe3q7GxkZVVlbG2rxer8rLy9XQ0HBA/2g0qmg0Gvt6165dkiRfdrZ8PgIFAADfnMSXGhzMJQhJvyjz448/1r59+xQMBuPag8GgwuHwAf2rqqoUCARiW2FhYbJLAgAA3SzlqzwqKysViURiW3Nzc6pLAgAALiX9I4/DDz9cWVlZamlpiWtvaWlRfn7+Af39fr/8fn+Ckb64FgQAAHwz9v+9e/C/h5N+hsLn86m0tFR1dXWxts7OTtXV1SkUCiX72wEAgDTQLfehmD17tqZOnapRo0bp9NNP14IFC7Rnzx5deuml3fHtAABAinVLoLjgggv00Ucfad68eQqHw/rWt76llStXHnChJgAAyAzddqfMadOmadq0ad01PAAASCMpX+UBAAB6PgIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYM11oFizZo3OPfdcFRQUyOPxaPny5XH7jTGaN2+eBg8erNzcXJWXl2vLli3JqhcAAKQh14Fiz549GjFihKqrqxPuv/POO3XffffpoYce0rp163TooYdq/Pjx2rt3r3WxAAAgPfVx+4IJEyZowoQJCfcZY7RgwQLddNNNOu+88yRJjz32mILBoJYvX64LL7zwgNdEo1FFo9HY121tbW5LAgAAKZbUayi2bt2qcDis8vLyWFsgEFBZWZkaGhoSvqaqqkqBQCC2FRYWJrMkAADwDUhqoAiHw5KkYDAY1x4MBmP79ldZWalIJBLbmpubk1kSAAD4Brj+yCPZ/H6//H5/qssAAAAWknqGIj8/X5LU0tIS197S0hLbBwAAMk9SA0VxcbHy8/NVV1cXa2tra9O6desUCoWS+a0AAEAacf2Rx+7du/XOO+/Evt66das2bdqkAQMGqKioSDNnztStt96q4447TsXFxZo7d64KCgo0ceLEZNYNAADSiOtAsWHDBp111lmxr2fPni1Jmjp1qhYvXqzrrrtOe/bs0ZVXXqnW1laNHTtWK1euVE5OTvKqBgAAacVjjDGpLuLL2traFAgEdNlPfyyfLzvV5QAA0Gu1t3fo0SVPKRKJqH///l/Zl2d5AAAAawQKAABgjUABAACsESgAAIA1AgUAALBGoAAAANYIFAAAwBqBAgAAWCNQAAAAawQKAABgjUABAACsESgAAIA1AgUAALBGoAAAANYIFAAAwBqBAgAAWCNQAAAAawQKAABgjUABAACsESgAAIA1AgUAALBGoAAAANYIFAAAwFqfVBcA9DR9g0cnbPckaDMux040RrcP7jBOombH+hx4sxL/zeLxuB0p4SjWvZNTR3J88kFTqksArHCGAgAAWCNQAAAAawQKAABgjUABAACsESgAAIA1VnkALrlcLJEUxsXgjvU5juG048CRnHp6vU5/mzhUk5QflsMgTj8Az4E1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du0yGzduNBs3bjSSzN133202btxo3n//fWPM58t88vLyzDPPPGNef/11c9555/W4JVtXX321CQQCZvXq1XFLtz799NNYn6uuusoUFRWZF1980WzYsMGEQiETCoVSWLV7c+bMMfX19Wbr1q3m9ddfN3PmzDEej8f87W9/M8ZkxhwT+fIqD2MyY57XXnutWb16tdm6dav5xz/+YcrLy83hhx9udu7caYzJjDka8/nS3z59+pjbbrvNbNmyxTzxxBPmkEMOMY8//nisTya8Bxnz+arAoqIic/311x+wLxOO59SpU82RRx4ZWzb69NNPm8MPP9xcd911sT6pOJZpGyiMMeb+++83RUVFxufzmdNPP92sXbs21SVZeemll4ykA7apU6caYz5f6jN37lwTDAaN3+83Z599tmlqakpt0S4lmp8kU1NTE+vz2WefmV/+8pfmsMMOM4cccoj50Y9+ZHbs2JG6orvgsssuM0OHDjU+n88cccQR5uyzz46FCWMyY46J7B8oMmGeF1xwgRk8eLDx+XzmyCOPNBdccEHcvRkyYY5fWLFihTn55JON3+83JSUl5uGHH47bnwnvQcYYs2rVKiMpYe2ZcDzb2trMjBkzTFFRkcnJyTFHH320ufHGG000Go31ScWx9BjzpVtrAQAAdEFaXkMBAAB6FgIFAACwRqAAAADWCBQAAMAagQIAAFgjUAAAAGsECgAAYI1AAQAArBEoAACANQIFAACwRqAAAADW/j+eh66m08pdXQAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Increasing the dimensions of the grid from 5 to 7\n",
      "Increasing the number of X from 1 to 5\n"
     ]
    },
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "k1rwnVq2qyoO"
   },
   "source": [
    "### Creating your own Side Channels\n",
    "You can send various kinds of data between a Unity Environment and Python but you will need to [create your own implementation of a Side Channel](https://docs.unity3d.com/Packages/com.unity.ml-agents@latest/index.html?subfolder=/manual/Custom-SideChannels.html#custom-side-channels) for advanced use cases.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   }
  }
 ]
}
